package cn.sylinx.horm.core.interceptor;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.HashSet;
import java.util.Set;

import cn.sylinx.horm.core.SqlClient;
import cn.sylinx.horm.interceptor.Invocation;
import cn.sylinx.horm.util.ClassUtil;

public class SqlClientProxy implements InvocationHandler {

    private static final Set<String> EXCLUDE_METHODS = new HashSet<>();

    static {
        EXCLUDE_METHODS.add("getDefaultClient");
        EXCLUDE_METHODS.add("getClientBy");
    }

    private final SqlClient sqlClient;

    public SqlClientProxy(SqlClient sqlClient) {
        this.sqlClient = sqlClient;
    }

    public static SqlClient create(SqlClient sqlClient) {
        return (SqlClient) Proxy.newProxyInstance(ClassUtil.getDefaultClassLoader(), new Class<?>[] { SqlClient.class },
                new SqlClientProxy(sqlClient));
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        if (Object.class.equals(method.getDeclaringClass())) {
            return method.invoke(this, args);
        }
        Invocation invocation = new Invocation(sqlClient, method, args);
        if (EXCLUDE_METHODS.contains(method.getName())) {
            return invocation.proceed();
        }
        return SqlClientInterceptorManager.INSTANCE.getInterceptor().intercept(invocation);
    }

    public SqlClient getTarget() {
        return sqlClient;
    }

}
